package com.tian.authen.security;

//import com.tian.authen.service.impl.CustomClientDetailsServiceImpl;
import com.tian.authen.exception.OauthServerWebResponseException;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;

/**
 * @author zhumengping
 * @title: AuthorizationServerConfig
 * @projectName zhump-cloud
 * @date 2023/8/3 18:14
 */
@Log4j2
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    //认证管理器
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private TokenStore tokenStore;





    /**
    * <pre>
     *     配置令牌端点安全策略
    * </pre>
    * @param security
    * @return void
    * @author zhump
    * @date 2023/8/3 18:16
    */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        log.info("[AuthorizationServerConfig-configure()]:security");
        security.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients();
    }

    /**
    * <pre>
     *     配置客户端
     *     通过查询数据库来进行校验客户端信息
    * </pre>
    * @param clients
    * @return void
    * @author zhump
    * @date 2023/8/3 18:17
    */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(customClientDetailsService());
    }

    /**
    * <pre>
     *     配置令牌服务
    * </pre>
    * @param endpoints
    * @return void
    * @author zhump
    * @date 2023/8/3 18:17
    */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        log.info("[AuthorizationServerConfig-configure()]:endpoints");
        //token 落库
        endpoints
                .exceptionTranslator(new OauthServerWebResponseException())
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .tokenStore(tokenStore)
                //登录成功之后，将默认请求action，转发到自定义请求action上去，再进到授权页面。
                .pathMapping("/oauth/confirm_access", "/mysqlTest")
                .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET);

        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(endpoints.getTokenStore());
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
        //30天
        tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));
        endpoints.tokenServices(tokenServices);


    }



    @Bean
    public TokenStore tokenStore(){
        return new JdbcTokenStore(dataSource);
    }

    @Bean
    public ClientDetailsService customClientDetailsService(){
        return new JdbcClientDetailsService(dataSource);
    }


}
